﻿using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using LogManager.Base.Data;
using LogManager.ViewModels;
using LogManager.ViewModels.Filter;
using System;
using MvcContrib.UI.Grid;
using Itenso.TimePeriod;
using MvcContrib.Sorting;
using MvcContrib.Pagination;
using System.Web.Routing;
using LogManager.Excel;
using LogManager.Base;
using LogManager.Helpers;

namespace LogManager.Controllers
{
    public class FilterController : BaseController
    {
        private IEventService _eventService;
        private IServerService _serverService;
        private ILogService _logService;
        private IEventTypeService _typeService;

        /// <summary>
        /// Creates new filter controller
        /// </summary>
        /// <param name="serverService">Server service</param>
        /// <param name="logService">Log service</param>
        /// <param name="eventService">Event service</param>
        /// <param name="typeService">Event type service</param>
        public FilterController(IServerService serverService, ILogService logService, IEventService eventService, IEventTypeService typeService)
        {
            _serverService = serverService;
            _logService = logService;
            _eventService = eventService;
            _typeService = typeService;
        }

        /// <summary>
        /// Predefined filter from to filter out events
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult Index()
        {
            //Build up view model
            var model = new FilterIndexViewModel
                            {
                                EventTypeFilter = new EventTypeFilterViewModel
                                                      {
                                                          Types = GetEventTypes(),
                                                          Properties = GetFilterNames(null),

                                                      },
                                EventFilter = new EventPropertyFilterViewModel
                                                  {
                                                      Levels = GetLevels(),
                                                      Users = GetUsers()
                                                  },
                                DateFilter = new EventDateFilterViewModel(),                                                 
                                SourceFilter = new EventSourceFilterViewModel
                                                   {
                                                       ServerNames = GetServerNames(),
                                                       LogNames = GetLogNames(null)
                                                   }
                            };

            return View(model);
        }

        /// <summary>
        /// Create excel with filtered results
        /// </summary>
        /// <param name="fileName">Name of the file to download</param>
        /// <param name="filter">EventParameterFilter to filter events</param>
        /// <param name="sortOptions">Sort options for the events</param>
        /// <param name="datePage">Date paging number</param>
        /// <returns>Excel file</returns>
        public ExcelResult<IEvent> ListDownload(string fileName, EventParameterFilter filter, GridSortOptions sortOptions, int datePage = 1)
        {
            //Load all events (no server get limit)
            var events = _eventService.GetEvents(new TimeRange(DateTime.Parse(filter.Start), DateTime.Parse(filter.End)), filter.ServerName, filter.LogName)
                .Filter(level: filter.Level, user: filter.User, type: filter.Type)
                .Search(filter.Property, filter.SearchValue)
                .OrderBy(sortOptions.Column, sortOptions.Direction)
                .All();
            
            //Create excel result
            var excel = new ExcelResult<IEvent>(events) { Title = fileName }
                .Columns(column =>
                {
                    column.For(e => e.ServerName);
                    column.For(e => e.LogName);
                    column.For(e => e.Type);
                    column.For(e => e.Level);
                    column.For(e => e.Message);
                    column.For(e => e.User);
                    column.For(e => e.TimeStamp);
                });
            return excel;
        }
        
        /// <summary>
        /// Get all server names for dropdownlist
        /// </summary>
        /// <returns>List of server names</returns>
        private IEnumerable<string> GetServerNames()
        {
            var items = _serverService.All().Select(s => s.ServerName).ToList();
            items.Insert(0, "All");
            return items;
        }

        /// <summary>
        /// Get all log names for dropdownlist for a server
        /// </summary>
        /// <param name="serverName">Get only logs for this server name</param>
        /// <returns>List of log names</returns>
        private IEnumerable<string> GetLogNames(string serverName)
        {
            var items = string.IsNullOrEmpty(serverName) ? new List<string>() : _logService.All(serverName).Select(l => l.LogName).ToList();
            items.Insert(0, "All");
            return items;
        }

        /// <summary>
        /// Get all users for dropdownlist
        /// </summary>
        /// <returns>List of users</returns>
        private IEnumerable<string> GetUsers()
        {
            var items = _eventService.GetUsers().ToList();
            items.Insert(0, "All");
            return items;
        }

        /// <summary>
        /// Get all levels for dropdownlist
        /// </summary>
        /// <returns>List of levels</returns>
        private IEnumerable<string> GetLevels()
        {
            var items = new List<string>
            {
                "Error",
                "Information",
                "Warning",
                "Critical"
            };
            items.Insert(0, "All");
            return items;
        }

        /// <summary>
        /// Get all event types for dropdownlist
        /// </summary>
        /// <returns>List of event types</returns>
        private IEnumerable<string> GetEventTypes()
        {
            var items = _typeService.All().Select(et => et.TypeId).ToList();
            return items;
        }

        /// <summary>
        /// Get all properties for a specified type
        /// </summary>
        /// <param name="typeName">Name of the type</param>
        /// <returns>List of possible properties</returns>
        private IEnumerable<string> GetFilterNames(string typeName)
        {
            var items = new List<string>();
            if (!string.IsNullOrEmpty(typeName) && typeName != "All")
            {
                var type = _typeService.Get(typeName);                
                items.AddRange(type.CommonProperties);
            }
            items.Insert(0, "All");
            return items;
        }

        /// <summary>
        /// Get filter names for dropdownlist as json
        /// </summary>
        /// <param name="typeName">Name of the type to get properties for</param>
        /// <returns>List of possible properties</returns>
        public JsonResult FilterNamesData(string typeName)
        {
            return Json(GetFilterNames(typeName), JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// Get log names for dropdownlist as json
        /// </summary>
        /// <param name="serverName">Name of the server to get log names</param>
        /// <returns>List of log names</returns>
        public JsonResult LogNamesData(string serverName)
        {
            return Json(GetLogNames(serverName), JsonRequestBehavior.AllowGet);
        }
        
    }
}
